import tkinter as tk
# 导入HTML标签库(pip install tkhtmlview)
from tkhtmlview import HTMLLabel
import random

# 最大能量数
power = 99
# 其它基的种类
R = 20
# 最大空间
size = 3
# 基本元素的化学性质（按照活跃度排序）：化合价，活跃度，稳定性
elements = {'C': [4, 0.8, 0.8], 'O': [2, 0.6, 0.8], 'H': [1, 0.5, 0.9], 'N': [5, 0.2, 0.6]}
# 游离元素分布情况
old_data = []
# 组合元素分布情况
new_data = []
names = list(elements.keys())

# 初始化数据
for i in range(size):
    old_data.append([])
    new_data.append([])
    # 随机生成元素
    for j in range(size):
        rand = random.randint(1, power)
        key = random.randint(0, len(names) - 1)
        name = names[key]
        # 生成字典对象
        old_data[i].append({})
        new_data[i].append({})
        for n in range(len(names)):
            nm = names[n]
            old_data[i][j][nm] = 0
            new_data[i][j][nm] = 0
        old_data[i][j][name] = rand  # 追加到二维数组中

# 显示界面
def show():
    html = '<table>'
    for i in range(size):
        html += '<tr>'
        for j in range(size):
            html += '<td>'
            # 显示游离元素
            for name in names:
                len_ = old_data[i][j][name]
                html += f'{name}({len_})、'
            # 显示组合元素
            html += '['
            for name in names:
                len_ = new_data[i][j][name]
                # 显示数量大于零的
                if len_ > 0:
                    html += f'{name}{len_}'
            html += ']'
            html += '</td>'
        html += '</tr>'
    html += '</table>'
    print(html)
    html_label.set_html(html)

# 时间线
def timer():
    # 此处最好是独立计算，为方便演示我们只模拟元素组合的过程：
    h = len(old_data)
    w = len(old_data[0])
    for yi in range(h):
        for xi in range(w):
            # 设置每个单元格反应的时间间隔（模拟时间线）
            sleep = (yi + 1) * xi  # 防止同时有多个时间线为0的情况
            root.after(1000 * sleep, lambda y=yi, x=xi, h=h, w=w: groups(y, x, h, w))
# 组合元素
def groups(yi, xi, h, w):
    # 开始组合其中一个单元格：坐标Y、坐标X
    # 找到一个元素，然后再找到它身边的元素，看看是否能够形成新的分子
    element = old_data[yi][xi]
    # 释放组合元素中不稳定的元素到游离元素中
    for name in names:
        # 不稳定性 = 1 - 稳定性
        num = round(new_data[yi][xi][name] * (1 - elements[name][2]))
        new_data[yi][xi][name] -= num
        element[name] += num
        print(f'释放 {name} {num}')
    # 由于 Python 并不支持并行计算，所以我们采用顺时针遍历单元格，最多五个单元格。
    # 上
    if yi - 1 >= 0:
        move(element, old_data[yi - 1][xi])
    # 右
    if xi + 1 < w:
        move(element, old_data[yi][xi + 1])
    # 下
    if yi + 1 < h:
        move(element, old_data[yi + 1][xi])
    # 左
    if xi - 1 >= 0:
        move(element, old_data[yi][xi - 1])
    # 开始组合元素
    group = {}
    # 统计所有活跃的元素
    for name in names:
        # 计算活跃的元素的数量
        num = round(element[name] * elements[name][1])
        # 将活跃元素移动到活跃元素组中，准备化学反应
        element[name] -= num
        # 合并剩余的组合元素
        group[name] = num + new_data[yi][xi][name]
        new_data[yi][xi][name] = 0
    # 以炭（C）为基础计算化合价
    C_size = group['C'] * elements['C'][0]  # 所有参与组合的碳元素化合价总数量
    # 其它元素总数：如果允许碳元素自己与自己组合就统计所有元素的数量
    print('活跃元素', group)
    sum_ = 0
    stop = False  # 是否停止组合
    for item in group:
        sum_ += group[item]  # 包含 C 元素自己
        # 处理大于 C 碳元素化合价的方法
        if sum_ > C_size:
            # 将剩余活跃元素移动至游离元素中
            # 方法 1：按照元素的活跃性进行优先组合，此处我们采用方法 1
            # 方法 2：按照元素的活跃性的比例进行组合
            if stop:
                element[item] += group[item]
                group[item] = 0
            else:
                element[item] += (sum_ - C_size)
                group[item] -= (sum_ - C_size)
            # 组成新的组合元素
            new_data[yi][xi][item] = group[item]
            stop = True
        else:
            # 小于 C 碳元素化合价处理方法
            new_data[yi][xi][item] = group[item]
    # 显示组合结果
    show()

# 移动游离的元素
def move(arr1, arr2):
    for i in range(len(names)):
        name = names[i]
        arr1[name] += arr2[name]
        arr2[name] = 0

# 创建主窗口
root = tk.Tk()
root.title("选择生命的基石")

# 创建文本框用于显示表格
html_label = HTMLLabel(root)
html_label.pack(padx=10, pady=10)

# 创建按钮
button = tk.Button(root, text="开始进化", command=timer)
button.pack()

# 初始显示
show()

# 运行主循环
root.mainloop()